from pyramid.httpexceptions import HTTPFound
from pyramid.security import (
    remember,
    forget,
)

from pyramid.view import (
    view_config,
    view_defaults,
    forbidden_view_config
)

from .security import (
    USERS,
    check_password
)


@view_defaults(renderer='home.pt')
class TutorialViews:
    def __init__(self, request):
        self.request = request
        self.logged_in = request.authenticated_userid

    @view_config(route_name='home')  # 定义路由名称为 'home' 的视图配置
    def home(self):
        """
        主页视图函数。

        无参数。

        返回值:
        dict: 包含一个键值对，其中键为 'name'，值为 'Home View'，用于在页面上显示主页视图的名称。
        """
        return {'name': 'Home View'}  # 返回用于显示主页名称的字典

    @view_config(route_name='hello', permission='edit')
    def hello(self):
        """
        该函数是一个视图配置，对应的路由名称为'hello'，需要'edit'权限才能访问。

        参数:
        self - 表示实例自身的引用

        返回值:
        返回一个字典，包含一个'name'键，其值为'Hello View'，用于在视图中展示。
        """
        return {'name': 'Hello View'}

    @view_config(route_name='login', renderer='login.pt')
    @forbidden_view_config(renderer='login.pt')
    def login(self):
        """
            处理用户登录请求的函数。

            路由名称为'login'，使用'login.pt'模板进行渲染。如果用户尝试访问受限制的资源，
            会被重定向到这个登录页面。此函数也会处理登录表单的提交。

            参数:
            - self: 表示类的实例。

            返回值:
            - 返回一个字典，包含登录页面所需的数据，如登录消息、登录表单的初始值等。
        """
        request = self.request  # 获取当前请求对象
        login_url = request.route_url('login')  # 获取登录页面的URL
        referrer = request.url  # 获取请求的来源URL
        if referrer == login_url:
            referrer = '/'  # 如果来源URL是登录页面本身，则将其改为根URL，避免循环登录
        came_from = request.params.get('came_from', referrer)  # 获取表单提交前的位置或默认为来源URL

        message = ''  # 初始化登录消息
        login = ''  # 初始化登录名
        password = ''  # 初始化密码
        if 'form.submitted' in request.params:  # 检查表单是否已提交
            login = request.params['login']  # 从请求中获取登录名
            password = request.params['password']  # 从请求中获取密码
            hashed_pw = USERS.get(login)  # 从用户数据库中获取登录名对应的加密密码
            if hashed_pw and check_password(password, hashed_pw):  # 验证密码
                headers = remember(request, login)  # 设置记住登录的头部信息
                return HTTPFound(location=came_from,
                                 headers=headers)  # 重定向回登录前的页面
            message = 'Failed login'  # 登录失败消息

        # 返回登录页面需要展示的数据
        return dict(
            name='Login',
            message=message,
            url=request.application_url + '/login',
            came_from=came_from,
            login=login,
            password=password,
        )

    @view_config(route_name='logout')  # 定义一个视图配置，对应于路由名 'logout'
    def logout(self):
        """
        处理用户登出逻辑。

        无参数传入，通过self访问类属性和方法。

        返回值: 返回一个HTTPFound对象，重定向到主页，并附带忘记会话的头信息。
        """
        request = self.request  # 获取当前请求对象
        headers = forget(request)  # 调用forget函数，生成用于忘记会话的头信息
        url = request.route_url('home')  # 根据路由名 'home' 生成回家页的URL
        # 返回一个重定向响应，前往home页面，并携带headers中的头信息
        return HTTPFound(location=url,
                         headers=headers)
